Primeras bases de datos

Cuadernos prácticos del Máster de Bioinformática (curso 2024-2025)

Author

Javier Álvarez Liébana

1 Primeras base de datos

Cuando analizamos datos solemos tener varias variables de cada individuo: necesitamos una «tabla» que las recopile.

1.1 Primer intento: matrices

La opción más inmediata son las matrices: concatenación de variables del mismo tipo e igual longitud.

Imagina que tenemos estaturas y pesos de 4 personas. ¿Cómo crear un dataset con las dos variables?

 

La opción más habitual es usando cbind(): concatenamos (bind) vectores en forma de columnas (c)

estaturas <- c(150, 160, 170, 180)
pesos <- c(63, 70, 85, 95)
datos_matriz <- cbind(estaturas, pesos)
datos_matriz
     estaturas pesos
[1,]       150    63
[2,]       160    70
[3,]       170    85
[4,]       180    95

También podemos construir la matriz por filas con la función rbind() (concatenar - bind - por filas - rows), aunque lo recomendable es tener cada variable en columna e individuo en fila como luego veremos.

rbind(estaturas, pesos) # Construimos la matriz por filas
          [,1] [,2] [,3] [,4]
estaturas  150  160  170  180
pesos       63   70   85   95
  • Podemos «visualizar» la matriz con View(matriz).

  • Podemos comprobar las dimensiones con dim(), nrow() y ncol(): las matrices son un tipo de datos tabulados (organizados en filas y columnas)

dim(datos_matriz)
[1] 4 2
nrow(datos_matriz)
[1] 4
ncol(datos_matriz)
[1] 2

También podemos «darle vuelta» (matriz transpuesta) con t().

t(datos_matriz)
          [,1] [,2] [,3] [,4]
estaturas  150  160  170  180
pesos       63   70   85   95

Dado que ahora tenemos dos dimensiones en nuestros datos, para acceder a elementos con [] deberemos proporcionar dos índices separados por comas: índice de la fila y de la columna

datos_matriz[2, 1] # segunda fila, primera columna
estaturas 
      160 
datos_matriz[1, 2] # primera fila, segunda columna 
pesos 
   63 

En algunas casos querremos obtener los datos totales de un individuo (una fila concreta pero todas las columnas) o los valores de toda una variable para todos los individuos (una columna concreta pero todas las filas). Para ello dejaremos sin rellenar uno de los índices

datos_matriz[2, ] # segundo individuo
estaturas     pesos 
      160        70 
datos_matriz[, 1] # primera variable
[1] 150 160 170 180

Mucho de lo aprendido con vectores podemos hacerlo con matrices, así podemos por ejemplo acceder a varias filas y/o columnas haciendo uso de las secuencias de enteros 1:n

datos_matriz[c(1, 3), 1] # primera variable para el primer y tercer individuo
[1] 150 170

También podemos definir una matriz a partir de un vector numérico, reorganizando los valores en forma de matriz (sabiendo que los elementos se van colocando por columnas).

z <- matrix(1:9, ncol = 3) 
z
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

Incluso podemos definir una matriz de valores constantes, por ejemplo de ceros (para luego rellenar)

matrix(0, nrow = 2, ncol = 3)
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0

1.1.1 Operaciones con matrices

Con las matrices sucede como con los vectores: cuando aplicamos una operación aritmética lo hacemos elemento a elemento

z/5
     [,1] [,2] [,3]
[1,]  0.2  0.8  1.4
[2,]  0.4  1.0  1.6
[3,]  0.6  1.2  1.8

Para realizar operaciones en un sentido matricial deberemos añadir %%, por ejemplo, para multiplicar matrices será %*%

z * t(z)
     [,1] [,2] [,3]
[1,]    1    8   21
[2,]    8   25   48
[3,]   21   48   81
z %*% t(z)
     [,1] [,2] [,3]
[1,]   66   78   90
[2,]   78   93  108
[3,]   90  108  126

También podemos realizar operaciones por columnas/filas sin recurrir a bucles con la función apply(), y le indicaremos como argumentos

  • la matriz
  • el sentido de la operación (MARGIN = 1 por filas, MARGIN = 2 por columnas)
  • la función a aplicar
  • argumentos extra que necesite la función

Por ejemplo, para aplicar una media a cada variable, será mean aplicada con MARGIN = 2 (misma función para cada columna)

# Media (mean) por columnas (MARGIN = 2)
apply(datos_matriz, MARGIN = 2, FUN = "mean")
estaturas     pesos 
   165.00     78.25 

1.2 💻 Tu turno (matrices)

Intenta realizar los siguientes ejercicios sin mirar las soluciones

📝 Modifica el código inferior para definir una matriz x de unos, de 3 filas y 7 columnas.

x <- matrix(0, nrow = 2, ncol = 3)
x
Code
x <- matrix(1, nrow = 3, ncol = 7)
x

📝 A la matriz anterior, suma un 1 a cada número de la matriz y divide el resultado entre 5. Tras ello calcula su transpuesta

Code
new_matrix <- (x + 1)/5
t(new_matrix)

📝 ¿Por qué el código inferior nos devuelve dicho mensaje de aviso?

matrix(1:15, nrow = 4)
Warning in matrix(1:15, nrow = 4): data length [15] is not a sub-multiple or
multiple of the number of rows [4]
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12    1

📝 Define la matriz x <- matrix(1:12, nrow = 4). Tras ello obtén los datos del primer individuo, los datos de la tercera variable, y el elemento (4, 1).

Code
x <- matrix(1:12, nrow = 4)
x[1, ] # primera fila
x[, 3] # tercera columna
x[4, 1] # elemento (4, 1)

📝 Define una matriz de 2 variables y 3 individuos tal que cada variable capture la estatura y la edad 3 personas, de manera que la edad de la segunda persona sea desconocida (ausente). Tras ello calcula la media de cada variable (¡nos debe de volver un número!)

Code
datos <- cbind("edad" = c(20, NA, 25), "estatura" = c(160, 165, 170))
apply(datos, MARGIN = 2, FUN = "mean", na.rm = TRUE) # media por columnas

📝 ¿Por qué devuelve error el código inferior? ¿Qué está mal?

matriz <- cbind("edad" = c(15, 20, 25), "nombres" = c("javi", "sandra", "carlos"))
matriz
     edad nombres 
[1,] "15" "javi"  
[2,] "20" "sandra"
[3,] "25" "carlos"
matriz + 1
Error in matriz + 1: non-numeric argument to binary operator

1.3 Segundo intento: data.frame

Las matrices tienen el mismo problema que los vectores: si juntamos datos de distinto tipo, se perturba la integridad del dato ya que los convierte (fíjate en el código inferior: las edades y los TRUE/FALSE los ha convertido a texto)

edades <- c(14, 24, NA)
soltero <- c(TRUE, NA, FALSE)
nombres <- c("javi", "laura", "lucía")
matriz <- cbind(edades, soltero, nombres)
matriz
     edades soltero nombres
[1,] "14"   "TRUE"  "javi" 
[2,] "24"   NA      "laura"
[3,] NA     "FALSE" "lucía"

De hecho al no ser números ya no podemos realizar operaciones aritméticas

matriz + 1
Error in matriz + 1: non-numeric argument to binary operator

Para poder trabajar con variables de distinto tipo tenemos en R lo que se conoce como data.frame: concatenación de variables de igual longitud pero que pueden ser de tipo distinto.

tabla <- data.frame(edades, soltero, nombres)
class(tabla)
[1] "data.frame"
tabla
  edades soltero nombres
1     14    TRUE    javi
2     24      NA   laura
3     NA   FALSE   lucía

Dado que un data.frame es ya un intento de «base de datos» las variables no son meros vectores matemáticos: tienen un significado y podemos (debemos) ponerles nombres que describan su significado

library(lubridate)

Attaching package: 'lubridate'
The following objects are masked from 'package:base':

    date, intersect, setdiff, union
tabla <-
  data.frame("edad" = edades, "estado" = soltero, "nombre" = nombres,
             "f_nacimiento" = as_date(c("1989-09-10", "1992-04-01", "1980-11-27")))
tabla
  edad estado nombre f_nacimiento
1   14   TRUE   javi   1989-09-10
2   24     NA  laura   1992-04-01
3   NA  FALSE  lucía   1980-11-27

¡TENEMOS NUESTRO PRIMER CONJUNTO DE DATOS! (estrictamente no podemos hablar de base de datos pero de momento como lo si fuesen). Puedes visualizarlo escribiendo su nombre en consola o con View(tabla)

1.3.1 Acceso a variables

Si queremos acceder a sus elementos, al ser de nuevo datos tabulados, podemos acceder como en las matrices (no recomendable): de nuevo tenemos dos índices (filas y columnas, dejando libre la que no usemos)

tabla[2, ]  # segunda fila (todas sus variables)
  edad estado nombre f_nacimiento
2   24     NA  laura   1992-04-01
tabla[, 3]  # tercera columna (de todos los individuos)
[1] "javi"  "laura" "lucía"
tabla[2, 1]  # primera característica de la segunda persona
[1] 24

Pero también tiene las ventajas de una «base» de datos : podemos aceder a las variables por su nombre (lo recomendable ya que las variables pueden cambiar de posición y ahora sí tienen un significado), poniendo el nombre de la tabla seguido del símbolo $ (con el tabulador, nos aparecerá un menú de columnas a elegir)

1.3.2 Funciones de consulta

  • names(): nos muestra los nombres de las variables
names(tabla)
[1] "edad"         "estado"       "nombre"       "f_nacimiento"
  • dim(): nos muestra las dimensiones (también nrow() y ncol())
dim(tabla)
[1] 3 4
  • Podemos acceder a las variables por su nombre
tabla[c(1, 3), "nombre"]
[1] "javi"  "lucía"
tabla$nombre[c(1, 3)]
[1] "javi"  "lucía"

1.3.3 Añadir variable

Si tenemos uno ya creado y queremos añadir una columna es tan simple como usar la función data.frame() que ya hemos visto para concatenar la columna. Vamos añadir por ejemplo una nueva variable, el número de hermanos de cada individuo.

# Añadimos una nueva columna con nº de hermanos/as
hermanos <- c(0, 2, 3)
tabla <- data.frame(tabla, "n_hermanos" = hermanos)
tabla
  edad estado nombre f_nacimiento n_hermanos
1   14   TRUE   javi   1989-09-10          0
2   24     NA  laura   1992-04-01          2
3   NA  FALSE  lucía   1980-11-27          3

1.4 Intento final: tibble

Las tablas en formato data.frame tienen algunas limitaciones. La principal es que no permite la recursividad: imagina que definimos una base de datos con estaturas y pesos, y queremos una tercera variable con el IMC

data.frame("estatura" = c(1.7, 1.8, 1.6), "peso" = c(80, 75, 70),
           "IMC" = peso / (estatura^2))
Error in data.frame(estatura = c(1.7, 1.8, 1.6), peso = c(80, 75, 70), : object 'peso' not found

En adelante usaremos el formato tibble (data.frame mejorado) del paquete {tibble}

library(tibble)
datos_tb <- 
  tibble("estatura" = c(1.7, 1.8, 1.6), "peso" = c(80, 75, 70), "IMC" = peso / (estatura^2))
class(datos_tb)
[1] "tbl_df"     "tbl"        "data.frame"
datos_tb
# A tibble: 3 × 3
  estatura  peso   IMC
     <dbl> <dbl> <dbl>
1      1.7    80  27.7
2      1.8    75  23.1
3      1.6    70  27.3
datos_tb <-
  tibble("estatura" = c(1.7, 1.8, 1.6), "peso" = c(80, 75, 70), "IMC" = peso / (estatura^2))
datos_tb
# A tibble: 3 × 3
  estatura  peso   IMC
     <dbl> <dbl> <dbl>
1      1.7    80  27.7
2      1.8    75  23.1
3      1.6    70  27.3

Las tablas en formato tibble nos permitirá una gestión más ágil, eficiente y coherente de los datos, con 4 ventajas principales:

  • Metainformación: si te fijas en la cabecera, nos dice ya automáticamente el número de filas y columnas, y el tipo de cada variable

  • Recursividad: permite definir las variables secuencialmente (como hemos visto)

  • Consistencia: si accedes a una columna que no existe avisa con un warning

datos_tb$invent
Warning: Unknown or uninitialised column: `invent`.
NULL
  • Por filas: crear por filas (copiar y pegar de una tabla) con tribble()
tribble(~colA, ~colB,
        "a",   1,
        "b",   2)
# A tibble: 2 × 2
  colA   colB
  <chr> <dbl>
1 a         1
2 b         2
Tip

El paquete {datapasta} nos permite copiar y pegar tablas de páginas web y documentos sencillos

1.5 💻 Tu turno (tb/df)

Intenta realizar los siguientes ejercicios sin mirar las soluciones

📝 Carga del paquete {datasets} el conjunto de datos airquality (variables de la calidad del aire de Nueva York desde mayo hasta septiembre de 1973). ¿Es el conjunto de datos airquality de tipo tibble? En caso negativo, conviértelo a tibble (busca en la documentación del paquete en https://tibble.tidyverse.org/index.html).

Code
library(tibble)
class(datasets::airquality)
airquality_tb <- as_tibble(datasets::airquality)

📝 Una vez convertido a tibble obtén el nombre de las variables y las dimensiones del conjunto de datos. ¿Cuántas variables hay? ¿Cuántos días se han medido?

Code
names(airquality_tb)
ncol(airquality_tb)
nrow(airquality_tb)

📝 Filtra solo los datos de la quinta observación

Code
airquality_tb[5, ]

📝 Filtra solo los datos del mes de agosto. ¿Cómo indicarle que queremos solo las filas que cumplan una condición concreta? (pista: en realidad todo son vectores “formateados”)

Code
airquality_tb[airquality_tb$Month == 8, ]

📝 Selecciona aquellos datos que no sean ni de julio ni de agosto.

Code
airquality_tb[airquality_tb$Month != 7 & airquality_tb$Month != 8, ]
airquality_tb[!(airquality_tb$Month %in% c(7, 8)), ]

📝 Modifica el siguiente código para quedarte solo con las variable de ozono y temperatura (sin importar qué posición ocupen)

airquality_tb[, 3]

📝 Selecciona los datos de temperatura y viento de agosto.

Code
airquality_tb[airquality_tb$Month == 8, c("Temp", "Wind")]

📝 Traduce a castellano el nombre de las variables.

Code
names(airquality_tb) <- c("ozono", "rad_solar", "viento", "temp", "mes", "dia") 

2 🐣 Caso práctico I: pinniped dataset

Del paquete {Biostatistics} usaremos el conunto de datos pinniped, que guarda los datos de peso de cuerpo y cerebro (desagregado por sexo y mono/poligamia) de 33 especies de mamíferos marinos.

Biostatistics::pinniped
                       Species Male_brain_g Female_brain_g Male_mass_Kg
1       Monachus schauinslandi        370.0             NA        173.0
2            Monachus monachus        480.0          480.0        260.0
3      Mirounga angustirostris        700.0          640.0       2275.0
4             Mirounga leonina       1431.3          898.8       3510.0
5       Leptonychotes weddelli        535.0          637.5        450.0
6            Ommatophoca rossi        425.0          530.0        153.8
7        Lobodon carcinophagus        578.2          538.8        220.5
8            Hydrurga leptonyx        765.0          660.0        324.0
9          Cystophora cristata        480.0          430.0        343.2
10         Erignathus barbatus           NA          460.0        312.5
11          Halichoerus grypus        342.5          272.5        233.0
12          Phoca groenlandica        297.5          252.5        145.0
13              Phoca fasciata        257.5          240.0         94.8
14                Phoca largha        257.5          250.0         97.0
15               Phoca caspica        165.0          160.0         70.5
16              Phoca sibirica        185.0          190.0         89.5
17               Phoca hispida        229.3          220.0         84.0
18              Phoca vitulina        362.3          265.0         97.1
19      Zalophus californianus        405.0          361.5        244.5
20          Eumetopias jubatus        747.5          575.0       1000.0
21              Otaria byronia        546.3          470.0        300.0
22            Neophoca cinerea        440.0          337.5        300.0
23          Phocarctos hookeri        417.5          370.0        364.0
24         Callorhinus ursinus        355.0          302.5        140.0
25     Arctocephalus townsendi           NA             NA        112.0
26     Arctocephalus philippii        415.0             NA        140.0
27 Arctocephalus galapagoensis        302.5          280.0         64.5
28     Arctocephalus australis        350.0          265.0         91.0
29      Arctocephalus forsteri        340.0          300.0        125.0
30       Arctocephalus gazella        360.0          320.0        155.0
31    Arctocephalus tropicalis        322.5          330.0        152.5
32      Arctocephalus pusillus        401.3          337.5        263.0
33           Odobenus rosmarus       1303.0         1340.5       1233.0
   Female_mass_Kg Mate_type
1           272.2      mono
2           275.0      mono
3           488.0      poly
4           565.7      poly
5           447.0      poly
6           164.0      mono
7           224.0      mono
8           367.0      mono
9           222.5      mono
10          326.0      mono
11          205.8      poly
12          139.0      mono
13           80.4      mono
14           71.3      mono
15           55.0      mono
16           85.0      mono
17           81.2      mono
18           85.2      mono
19           81.0      poly
20          287.5      poly
21          144.0      poly
22           78.6      poly
23          114.7      poly
24           33.3      poly
25           49.6      poly
26           48.1      poly
27           27.4      poly
28           48.5      poly
29           38.1      poly
30           45.0      poly
31           50.0      poly
32           64.1      poly
33          811.5      poly

2.1 Pregunta 1

Comprueba si los datos están en formato tibble. En caso negativo conviértelo.

Code
# chequeamos si es tibble
library(tibble)
is_tibble(Biostatistics::pinniped)

# Convertimos a tibble
pinniped_tb <- as_tibble(Biostatistics::pinniped)

2.2 Pregunta 2

¿Cuántos registros hay? ¿Cuántas variables? ¿De qué tipo es cada una? ¿Cuáles son sus nombres?

Code
nrow(pinniped_tb)
ncol(pinniped_tb)
names(pinniped_tb)

2.3 Pregunta 3

Incorpora una variable nueva llamada phoca que sea de tipo lógico y que nos diga si una especie es de la categoría Phoca o no.

Code
# tienes más funcionalidades con textos del paquete stringr
# arriba en el workbook
pinniped_tb$phoca <- str_detect(pinniped_tb$Species == "Phoca")

2.4 Pregunta 4

¿A qué sexo le pesa más el cerebro: a las hembras o a los machos?

Code
# ¿a quién le pesa más el cerebro?
mean(pinniped_tb$Male_brain_g, na.rm = TRUE) >
  mean(pinniped_tb$Female_brain_g, na.rm = TRUE)

2.5 Pregunta 5

¿A quienes les pesa más el cuerpo a los monógamos o a los polígamos? Recuerda que tienes los pesos divididos por sexos en variables distintas que tendrás que juntar de alguna forma

Code
# ¿a quién le pesa más el cerebro?
mean(c(pinniped_tb$Male_mass_Kg[pinniped_tb$Mate_type == "mono"],
       pinniped_tb$Female_mass_Kg[pinniped_tb$Mate_type == "mono"])) >
  mean(c(pinniped_tb$Male_mass_Kg[pinniped_tb$Mate_type == "poly"],
         pinniped_tb$Female_mass_Kg[pinniped_tb$Mate_type == "poly"]))

2.6 Pregunta 6

Incopora una nueva variable llamada dif_m_f que represente la diferencia entre el peso del cerebro entre machos y hembras (machos - hembras) para cada especie.

Code
pinniped_tb$dif_m_f <- pinniped_tb$Male_brain_g - pinniped_tb$Female_brain_g
pinniped_tb

3 🐣 Caso práctico II: análisis de Taylor Swift

3.1 Pregunta 1

Instala el paquete {taylor} EN LA CONSOLA y tras ello cárgalo

# SIEMPRE EN CONSOLA
# install.packages("taylor")
library(taylor)

En dicho paquete tenemos el dataset taylor_album_songs con las características de las canciones de álbum de Taylor Swift (se excluyen canciones fuera de álbumes y solo se consideran las canciones de su propiedad). Haz que aparezca el dataset en el documento.

Code
taylor_album_songs

3.2 Pregunta 2

¿Cuántas canciones hay guardadas? ¿Cuántas características (variables) hay guardadas de cada una?

Code
ncol(taylor_album_songs)
nrow(taylor_album_songs)

3.3 Pregunta 3

Obtén el nombre de los álbumes (únicos) que hay contenidos en el dataset. ¿Cuántos hay?

Code
unique(taylor_album_songs$album_name)
length(unique(taylor_album_songs$album_name))

3.4 Pregunta 4

¿En cuántas canciones hay una colaboración con otro artista? Si hay colaboración, su nombre viene guardado en featuring

Code
# Si nos preguntan por canciones (es decir, registros en este caso) bastaría con
# saber hay colaboraciones donde no hay NA, así que me basta con contar los NA
sum(!is.na(taylor_album_songs$featuring))

# Si me preguntasen por aristas únicos (sin contar repetidos) sería
# quitar antes los NA (para que no los cuente como un artista más)
# y eliminar colaboradores repetidos
length(unique(taylor_album_songs$featuring[!is.na(taylor_album_songs$featuring)]))

3.5 Pregunta 5

Crea un nuevo tibble solo con las variables album_name, album_release, track_name, featuring y duration_ms. Tras ello ordena por fecha de más reciente a más antigua

Code
nuevo_tb <-
  taylor_album_songs[, c("album_name", "album_release", "track_name",
                         "featuring", "duration_ms")]
nuevo_tb[order(nuevo_tb$album_release, decreasing = TRUE), ]

3.6 Pregunta 6

Añade al anterior dataset dos nuevas variables con el mes y año de lanzamiento (usa la variable album_release). ¿En qué mes ha lanzado más álbumes?

Code
library(lubridate)
nuevo_tb$mes <- month(nuevo_tb$album_release)
nuevo_tb$year <- year(nuevo_tb$album_release)

# opción corta
table(nuevo_tb$mes)

# opción larga
sum(nuevo_tb$mes == 1)
sum(nuevo_tb$mes == 2)
sum(nuevo_tb$mes == 3)
# ....
sum(nuevo_tb$mes == 12)

3.7 Pregunta 7

Obtén la media de duración de las canciones en minutos (variable duration_ms está en milisegundos). Extrae todos los datos de la canción que más dura (toda su fila).

Code
# Pasamos los milisegundos a minutos y luego la media excluyendo NA
mean(nuevo_tb$duration_ms / 60000, na.rm = TRUE)

# primero quitamos las que tiene duración ausente
nuevo_tb <- nuevo_tb[!is.na(nuevo_tb$duration_ms), ]

# Para obtener los datos de la canción que más dura tenemos 3 opciones:

# 1. extrayendo aquella canción cuya duración coincida con el máximo
nuevo_tb[nuevo_tb$duration_ms == max(nuevo_tb$duration_ms), ]

# 2. ordenando de más duración a menos y quedándonos con la primera fila
nuevo_tb[order(nuevo_tb$duration_ms, decreasing = TRUE), ][1, ]

# 3. con `which.max()` (en lugar de devolver el máximo nos devuelve la posición donde está)
nuevo_tb[which.max(nuevo_tb$duration_ms), ]

4 🐣 Caso práctico III: salto de longitud (practicando textos)

Para practicar textos y tibbles vamos a usar el dataset salto_longitud.csv que tienes guardado en la carpeta de datos, que guarda cómo ha progresado el récord de salto de longitud masculino. Dicha tabla ha sido extraída directamente de la wikipedia https://en.wikipedia.org/wiki/Men%27s_long_jump_world_record_progression#Low_altitude_record_progression_1965%E2%80%931991

load(file = "./datos/salto_longitud.RData")

Aunque no forma parte del curso, puedes ver debajo si quieres el código que se ha usado para extraer la tabla directamente de la wikipedia

Code
library(rvest)
library(tidyverse)
wiki_jump <- 'https://en.wikipedia.org/wiki/Men%27s_long_jump_world_record_progression'
long_jump <- read_html(wiki_jump)
salto_longitud <- html_table(html_node(long_jump, 'table'))

4.1 Pregunta 1

¿Cuántos registros hay? ¿Cuántas variables? ¿De qué tipo es cada una? ¿Cuáles son sus nombres? ¿Qué crees que significan?

Code
nrow(salto_longitud)
ncol(salto_longitud)
names(salto_longitud)

# tenemos 19 récords y 5 variables: la marca (en metros, pies y pulgadas), el viento que hacía, la persona que batió el record, el lugar y la fecha.

4.2 Pregunta 2

Crea una nueva variable llamada Mark (sustituye a la anterior) en la que hayas extraído la marca en metros (y convertida a número). Práctica antes con un valor de juguete, por ejemplo, si tuviésemos `x <- “7.61 m (24 ft 11+1/2 in)”, ¿cómo podríamos quedarnos solo con la marca en metros?

Code
# Sabemos que el patrón es 1 número, un ., y dos decimales, así que
# usamos str_extract para extraer ese patrón que le indicamos
# con una expresión regular.
salto_longitud$Mark <-
  str_extract(salto_longitud$Mark, pattern = "[0-9][.][0-9]{2}")

# Tras ello convertimos a número
salto_longitud$Mark <- as.numeric(salto_longitud$Mark)

# importante: ahora en la cabecera debajo de mark pone <dbl>, es un número
salto_longitud 

4.3 Pregunta 3

Crea una nueva variable llamada Wind (sustituye la original) en la que tengas el viento convertido a número.

Code
salto_longitud$Wind <- as.numeric(salto_longitud$Wind)
salto_longitud

¿En cuántos récords no había viento? ¿En cuántos no tenemos registros de dicha medida?

Code
# Con viento 0
sum(salto_longitud$Wind == 0, na.rm = TRUE)

# Sin registros
sum(is.na(salto_longitud$Wind))

# importante: ausente y 0 no es lo mismo

4.4 Pregunta 4

Crea una nueva variable llamada country que extraiga las siglas de los países de la variable Athlete

Code
# Primero extraemos con los paréntesis (es más fácil detectarlo)
salto_longitud$country <-
  str_extract(salto_longitud$Athlete, pattern = "[(][A-Z]{3}[)]")

# Luego los eliminamos los ( y los ) (de ahí la barra vertical en medio)
# Fíjate que para que entienda que es un caracter especial (paréntesis)
# se lo pasamos como \\( y como \\). Ppasaría lo mismo si queremos detectar,
# por ejemplo, un punto, con \\.
salto_longitud$country <- str_remove_all(salto_longitud$country, "\\(|\\)")

4.5 Pregunta 5

Ordena la tabla por orden alfabético de las siglas

Code
salto_longitud <- salto_longitud[order(salto_longitud$country), ]

4.6 Pregunta 6

Reemplaza la variable Date por la fecha correcta en formato fecha

Code
# primero eliminamos todos los [?]
salto_longitud$Date <-
  str_remove_all(salto_longitud$Date, pattern = "\\[[0-9]{1}\\]")

# luego atendemos el caso particualr de [note 1]
salto_longitud$Date <-
  str_remove_all(salto_longitud$Date, pattern = "\\[note 1\\]")

# tras depurar convertimos a fecha
salto_longitud$Date <- dmy(salto_longitud$Date)
salto_longitud

4.7 Pregunta 7

¿Cuántos récords no son de Estados Unidos? ¿Qué porcentaje representa respecto al total?

Code
# total absoluto
sum(salto_longitud$country != "USA")

# porcentaje relativo
100*sum(salto_longitud$country != "USA") / length(salto_longitud$country)

4.8 Pregunta 8

Para cada récord, calcula los metros de mejora respecto al anterior, y guárdalo en la base de datos. Pista: prueba bien la función diff() y chequea la longitud de lo que te devuelve.

Code
# Usamos la función diff que, dado un vector, calcula las diferencias
# fíjate que el primero no conocemos la mejora (ya que no hay registro previo)
salto_longitud$mejora <- c(NA, diff(salto_longitud$Mark))